POV-Ray : Newsgroups : povray.binaries.images : RSoCP (one more) : Re: RSoCP (one more) Server Time
5 Nov 2024 14:20:12 EST (-0500)
  Re: RSoCP (one more)  
From: Trevor G Quayle
Date: 15 Aug 2006 16:55:01
Message: <web.44e2341471ada471c150d4c10@news.povray.org>
"Gail Shaw" <initialsurname@sentech sa dot com> wrote:
> "Trevor G Quayle" <Tin### [at] hotmailcom> wrote in message
> news:web.44e2139771ada471c150d4c10@news.povray.org...
> >
> > Thanks. The floor is created from heightfields using user-defined
> functions
> > which I have been playing with a bit recently.
>
> They look great, like the stone tiles found on patios.
>
> Could you go into a bit more detail about how you do them?

I pursued developing this out of dissatisfaction with the results I was
getting through CSG and surface normals when making tiles.

Not sure how familiar you are with heightfields.  Typically they use an
external image, however, POVRay allows them to use internal images as well.
 This includes definable pigment patterns as well as functions. The basics
steps are as follows (note that heigtfields evaluate the pattern functions
on the x-y plane from <0,0,0> to <1,1,0> and are created on the x-z plane
from <0,0,0> to <1,0,1>):

Create basic tile pattern.  For this I used the boxed pigment.  The boxed
pattern centers on the origin and is 2 units wide so scale and translate it
so it is 1x1 with its corner at the origin.  Using a pigment_map controls
the size of the flat area, the bevels and the gap of the tiles (I'm using a
power function to correspond with the poly_wave waveform). In my example,
the gap is from 0 to 0.01,the bevel from 0.01 to 0.1 and the flat from 0.1
to 1.0 (from edge to centre of tile).  Using a poly_wave waveform allows
the bevel shape to be adjusted. (poly_wave 1.0 = linear, <1.0 = convex). We
could leave the pigment here and have only one tile per HF, however, when
tiled,each one would be identical. Define how many tiles we want per HF
before repeating (TPU).  Since boxed is not a repeating pattern, we need to
apply 2 repeat warps.  Finally scale the pigment down by TPU so the section
we want is within the <0,0,0>-<1,1,0> region:

#declare TPU=8; //tiles per unit

#declare PTILE =pigment{boxed pigment_map{[pow(0.01,0.2) rgb 0][pow(0.1,0.2)
rgb 1]} scale 1/2 translate <1/2,1/2,0>  warp{repeat x} warp{repeat y} scale
1/TPU poly_wave 0.2}

Next the pigment is simply converted to a function pattern. This makes
combining it with our tile texture pattern easier and more flexible:

#local FTILEA = function {pigment{PTILE}}

Next we define a function pattern for the texture we want the tile to have
(scaled according to the tile size again):

#local FTILEB = function {pigment{granite scale 1/2/TPU*2}}

Next we want to combine the 2 functions to give our final tile pattern (note
that we need to use .gray flag here to convert the rgb vector to a float).
This can require a bit of futzing around to get what you want.  Remember
though that the HF height is equal to the function value from 0 to 1,
beyond 1 it will wrap back to 0 effectively (y MOD 1) so we want to try to
keep the total function values between 0 and 1 to avoid confusion (Using
min/max functions can help clip the values and add effects).  In may
example here, I only want the flat part to be textured so the select
function allows me to grap only the top of the tile (i.e. where FTILEA >
0.99) and subtract the texture pattern (FTILEB) from it.  To maintain some
flat areas, 0.3 is subtracted from FTILEB (leaving ~30% of the tile area
flat after the min function is applied), this value is then adjusted to the
desired depth of the texture (0.15 in this case). The second instance of
FTILEB here is to add some additional rough texture at 1/10 the scale.

#local FTILE = function
{min(FTILEA(x,y,z).gray-select(FTILEA(x,y,z).gray-0.99,0,1)*((FTILEB(x,y,z).gray-0.3)*0.15-FTILEB(x*10,y*10,z*10).gray*
0.01),1)}

This function is then simply applied as a function pattern to a HF.  The HF
isintersected with a box to give a solid tile, and then scaled to give the
desired tile size.  For the HF, the resolution can be changed as needed
(800,800 is used here) and 'smooth' may be added as desired.

#declare THK=0.1;

#declare Tile=
intersection{
  height_field{function 800,800 {pattern{ function{FTILE(x,y,z)} }}}
  box{0 1}
  translate <-1/2,0,-1/2> //centre tile group
  scale <TPU,THK,TPU>  //each tile is 1x1xTHK
}

//END

I hope this was somewhat informative for you.  It seems that not many people
are aware of the full capabilities if HFs.  Of course, the functions used
here were for what I wanted, any other definable function (even multiple
functions) can be used in any type of combination (+,-,x,etc.) as desired.
The important part is to scale the pattern to the <0,0,0><1,1,0> region and
to keep the values between 0 and 1.
If you have any further questions, please post them. And please posts any
nice results you get.


-tgq


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.